package tplenguajes;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.CommonTree;

import tplenguajes.TParser.s_return;
import tplenguajes.grafo.AFD;
import tplenguajes.grafo.AFND;

class Main {

	private static String regex, file;

	static TLexer lexer;

	public static void main(String[] args) {
		try {
			lexer = new TLexer();

			if (args.length < 1) {
				System.err
						.println("Modo de uso: java -jar tplenguajes-0.1-jar-with-dependencies.jar regex file");
			} else {
				regex = args[0];
				file = args[1];
				parse();
			}
		} catch (Exception ex) {
			System.err.println("Error en el parser ANTLR:");
			ex.printStackTrace();
		}
	}

	public static void parse() throws Exception {

		try {
			parseSource(regex);
		} catch (Exception ex) {
			System.err.println("Error de parsing");
			ex.printStackTrace();
		}

	}

	public static void parseSource(String source) throws Exception {
		try {
			System.out.println("Parseando regex: " + source);
			lexer.setCharStream(new ANTLRStringStream(source));

			CommonTokenStream tokens = new CommonTokenStream(lexer);

			TParser parser = new TParser(tokens);
			s_return psrReturn = parser.s();

			CommonTree t = (CommonTree) psrReturn.getTree();

			// muestro el árbol por consola
			printTree(t, 1);

			// Preparo el alfabeto
			Set<String> alphabet = new HashSet<String>();
			for (char c = 'a'; c < 'z' + 1; c++)
				alphabet.add(Character.toString(c));
			for (char c = 'A'; c < 'Z' + 1; c++)
				alphabet.add(Character.toString(c));
			for (char c = '0'; c < '9' + 1; c++)
				alphabet.add(Character.toString(c));
			alphabet.add(" ");

			System.out.println("Generando AFND...");
			AFND<String> afnd = new AFND<String>(t, alphabet);
			System.out.println(afnd.toString());
			System.out.println("Convirtiendo a AFD...");
			AFD<String> afd = new AFD<String>(afnd);
			System.out.println(afd.toString());
			
			//Iterable<String> str = getIterableString("asd fakjdsfl");
			//afd.acceptsString(str);

			try {
				FileOutputStream afndstream = new FileOutputStream("afnd.dot",
						false);
				afndstream.write(afnd.toString().getBytes());
				afndstream.close();
				FileOutputStream afdstream = new FileOutputStream("afd.dot",
						false);
				afdstream.write(afd.toString().getBytes());
				afdstream.close();
			} catch (Exception e) {
				System.out.println("Error al escribir los archivos .dot");
				System.exit(1);
			}

		} catch (Exception ex) {
			System.err.println("Error de parsing:\n\n");
			ex.printStackTrace();
		}
	}

	public static void printTree(CommonTree t, int indent) {
		if (t != null) {
			StringBuffer sb = new StringBuffer(indent);
			for (int i = 0; i < indent; i++)
				sb = sb.append("   ");
			for (int i = 0; i < t.getChildCount(); i++) {
				System.out.println(sb.toString() + t.getChild(i).toString()
						+ "  " + t.getChild(i).getChildCount());
				printTree((CommonTree) t.getChild(i), indent + 1);
			}
		}
	}
	private static List<String> getIterableString(String string){
		List<String> iterableString = new ArrayList<String>();
		
		for(int i=0; i<string.length(); i++){
			iterableString.add(string.substring(i, i+1));
		}
		
		return iterableString;
	}
}
